package cn.plem.ml;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.ml.Ml;
import org.opencv.ml.TrainData;

public class CsvTrain {

	public static Path path = Paths.get("data.csv");
	int cols;

	String label;

	public CsvTrain(String name) {
		label = String.format("%s.label.txt", name);
	}

	public TrainData trainData() throws IOException {
		return trainData(path);
	}

	public TrainData trainData(Path csv) throws IOException {
		return trainData(csv, CvType.CV_32SC1);
	}

	public TrainData trainData(Path csv, int cvtype) throws IOException {
		List<String> csvData = Files.readAllLines(csv).stream().filter(t -> !t.trim().equals(""))
				.collect(Collectors.toList());
		int rows = csvData.size();
		cols = csvData.get(0).split(",").length - 1;

		Mat trainingDataMat = new Mat(rows, cols, CvType.CV_32FC1);
		trainingDataMat.put(0, 0, data(csvData));

		Mat labelsMat = new Mat(rows, 1, CvType.CV_32FC1);
		labelsMat.put(0, 0, label(csvData));
		if (cvtype == CvType.CV_32SC1) {// svm
			labelsMat.convertTo(labelsMat, CvType.CV_32SC1);
		}
		
		return TrainData.create(trainingDataMat, Ml.ROW_SAMPLE, labelsMat);
	}

	public List<String> label() throws IOException {
		Path path = path(label);
		return Files.readAllLines(path);
	}

	private float[] label(List<String> csvData) throws IOException {
		List<String> list = new ArrayList<>();

		float[] labels = new float[csvData.size()];
		for (int i = 0; i < labels.length; i++) {
			String[] s = csvData.get(i).split(",");
			String l = s[s.length - 1];
			if (!list.contains(l)) {
				list.add(l);
			}
			labels[i] = (float) list.indexOf(l);
		}
		String txt = list.stream().collect(Collectors.joining(System.lineSeparator()));
		Files.write(path(label), txt.getBytes());
		return labels;
		/*
		 * return csvData.stream().mapToInt(t -> { String[] s = t.split(","); int
		 * i=label.indexOf(s[s.length - 1]); return i; }).toArray();
		 */
	}

	private float[] data(List<String> csvData) {
		int rows = csvData.size();
		float[] d = new float[rows * cols];
		for (int i = 0; i < rows; i++) {
			String[] s = csvData.get(i).split(",");
			int k = i * cols;
			for (int j = 0; j < s.length - 1; j++) {
				d[j + k] = Float.parseFloat(s[j]);
			}
		}
		return d;
	}

	public static Path path(String name) {
		return Paths.get(path.toFile().getAbsoluteFile().getParent(), name);
	}

}
